﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Xml.Serialization;
using AG.Utilities;

namespace AG.Utilities
{
    public class Logger
    {
        private static bool Initialized;
        private static StreamWriter swLog;
        private static String loggingFolder;
        private static Object thisLock = new Object();

        
        public static void Initialize(string folder)
        {

            loggingFolder = folder;

            Initialized = true;
        }

        public static void WriteLine(String line)
        {
            lock (thisLock)
            {

                if (Initialized)
                {
                    using (swLog = new StreamWriter(loggingFolder + @"\log.txt", true))
                    {
                        swLog.WriteLine(line);
                    }
                }
            }
        }

        public static void Debug(string message)
        {
            WriteLine(DateTime.Now.ToString("dd-MM-yyyy hh:mm") + "- " + message);

        }


        public static void ThrowAndLogError(Exception ex)
        {
            String errorMessage = GetErrorMessage(ex);

            WriteLine(errorMessage);
            throw new Exception(errorMessage);
        }

        public static void ThrowError(Exception ex)
        {
            throw new Exception(GetErrorMessage(ex));
        }

        private static String GetErrorMessage(Exception ex)
        {
            return DateTime.Now.ToString("dd-MM-yyyy hh:mm") + "! Error in " + Logger.GetSource() + ": " + ex.Message + " in " + ex.Source;
        }
        private static String GetErrorMessageExtraInfo(Exception ex, String info)
        {
            return DateTime.Now.ToString("dd-MM-yyyy hh:mm") + "! Error in " + Logger.GetSource() +  ", extra info:" + info + ", message: " + ex.Message + " in " + ex.Source ;
        }



        public static void Error(String extraInfo, Exception ex)
        {
            try
            {
                String errorMessage = GetErrorMessageExtraInfo(ex, extraInfo);

                WriteLine(errorMessage);

            }
            catch (Exception)
            {

            }
        }


        public static void Error(Exception ex)
        {
            try
            {
                String errorMessage = GetErrorMessage(ex);

                WriteLine(errorMessage);

            }
            catch (Exception)
            {

            }

        }


        public static void Error(Exception exception, String source, string extraInfo)
        {

            string messageShort = "";

            if (exception.Message.Length > 50)
                messageShort = exception.Message.Substring(0, 50) + "...";
            else
                messageShort = exception.Message;

            string error = @"
                <errorEntry date='{date}' msg='{messageShort}'>
                    <message>{message}</message>
                    <source>{source}</source>
                    <extraInfo>{extraInfo}</extraInfo>
                    {exception}
                </errorEntry>".Replace("{date}", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")).Replace(
                                       "{messageShort}", System.Web.HttpUtility.HtmlEncode(messageShort.Replace("'", "\"")))
                                       .Replace(
                                       "{message}", System.Web.HttpUtility.HtmlEncode(exception.Message)).Replace(
                                       "{source}", System.Web.HttpUtility.HtmlEncode(source)).Replace(
                                       "{extraInfo}", extraInfo).Replace(
                                       "{exception}", BuildXmlException(exception, false));


            WriteLine(error);

        }

        private static string GetSource()
        {
            try
            {
                StackFrame frame1 = new StackFrame(3, true);
                string source = frame1.GetMethod().DeclaringType.FullName + "." + frame1.GetMethod().Name;

                return source;

            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Logger.GetSource", "");
                return "";
            }


        }

        public static String BuildXmlException(Exception ex, bool inner)
        {
            String strElementName;

            if (inner)
            {
                strElementName = "InnerException";
            }
            else
            {
                strElementName = "Exception";
            }

            String strException = @"
<{elementName}>
    <Source>{source}</Source>
    <Message>{message}</Message>".Replace("{elementName}", strElementName).Replace("{source}", ex.Source).Replace("{message}", ex.Message);

            if (ex.InnerException != null)
            {
                strException += BuildXmlException(ex.InnerException, true);
            }

            strException += @"
</{elementName}>".Replace("{elementName}", strElementName);

            return strException;

        }

        public static string ConvertObjectToXML(Object objectToSerialize)
        {
            try
            {
                String XmlizedString = null;
                MemoryStream memoryStream = new MemoryStream();
                XmlSerializer xs = new XmlSerializer(objectToSerialize.GetType());
                XmlFragmentWriter xmlTextWriter = new XmlFragmentWriter(memoryStream, Encoding.UTF8);
                xs.Serialize(xmlTextWriter, objectToSerialize);
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
                return XmlizedString;

            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Logger.ConvertObjectToXML", "");
                return "";
            }


        }

        private static String UTF8ByteArrayToString(Byte[] characters)
        {

            UTF8Encoding encoding = new UTF8Encoding();
            String constructedString = encoding.GetString(characters);
            return (constructedString);
        }

    }
}
